package com.imm.da.utils

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint
import android.os.Parcelable
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.text.TextUtils
import android.util.Base64
import android.view.View
import androidx.compose.runtime.Composable
import androidx.core.app.ActivityCompat
import java.io.InputStreamReader
import java.io.LineNumberReader
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import java.util.UUID
import javax.crypto.Cipher
import javax.crypto.Mac
import javax.crypto.SecretKey
import javax.crypto.spec.SecretKeySpec

/**
 * <p>------------------------------------------------------
 * <p> Copyright (C) 2021 zhangmz, All rights reserved.
 * <p> If there is technical discussion, you can contact zhangmz90@foxmail.com
 * <p>------------------------------------------------------
 * <p> des
 * <p>
 *
 * @author Created by zhangmz90
 * @date on 2021 2021/11/14 13:39
 */
object AppUtil {

    const val HMAC_SHA1 = "HmacSHA1"
    const val HMAC_MD5 = "HmacMD5"
    const val HMAC_SHA256 = "HmacSHA256"
    const val HMAC_SHA512 = "HmacSHA512"

    /**
     * Parcelable 类转化 map
     */
    fun entityToMap(parcelable: Parcelable): Map<String, Any?> {
        val map: MutableMap<String, Any?> = HashMap()
        try {
            for (field in parcelable.javaClass.declaredFields) {
                val flag = field.isAccessible
                field.isAccessible = true
                val o = field[parcelable]
                if (o is Parcelable.Creator<*>) {
                    continue
                }
                map[field.name] = o
                field.isAccessible = flag
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return map
    }

    /**
     * Parcelable 类转化 map
     */
    fun entityToMapString(parcelable: Parcelable): Map<String, String> {
        val map: MutableMap<String, String> = HashMap()
        try {
            for (field in parcelable.javaClass.declaredFields) {
                val flag = field.isAccessible
                field.isAccessible = true
                val o = field[parcelable] ?: continue
                if (o is Parcelable.Creator<*>) {
                    continue
                }
                map[field.name] = o.toString()
                field.isAccessible = flag
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return map
    }

    /**
     * 指定类型加密
     * @param message 需要加密的输入参数
     * @param key 密钥
     * @param algorithm 选择加密算法
     * @return 加密后的值
     */
    fun encrypt(message: String, key: String, algorithm: String): String = runCatching {
        val data = key.toByteArray(StandardCharsets.UTF_8)
        // 根据给定的字节数组构造一个密钥，第二个参数指定一个密钥的算法名称，生成HmacSHA1专属密钥
        val secretKey: SecretKey = SecretKeySpec(data, algorithm)
        // 生成一个指定Mac算法的Mac对象
        val mac = Mac.getInstance(algorithm)
        // 用给定密钥初始化Mac对象
        mac.init(secretKey)
        val text = message.toByteArray(StandardCharsets.UTF_8)
        val encryptByte = mac.doFinal(text)
        val result = Base64.encodeToString(encryptByte, Base64.NO_WRAP)
        result
    }.getOrDefault(message)

    /**
     * md5加密
     */
    fun toMd5(message: String) = runCatching {
        //获取一种摘要算法
        val builder = StringBuilder()
        val instance = MessageDigest.getInstance("MD5")
        val digest = instance.digest(message.toByteArray(StandardCharsets.UTF_8))
        for (b in digest) {
            if (Integer.toHexString(0xFF and b.toInt()).length == 1) {
                builder.append("0").append(Integer.toHexString(0xFF and b.toInt()))
            } else {
                builder.append(Integer.toHexString(0xFF and b.toInt()))
            }
        }
        builder.toString()
    }.getOrDefault(message)

    /**
     * java自带的只支持 PKCS5
     */
    private val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")

    /**
     * AES 加密
     */
    fun textEncryption(content: String, key: String): ByteArray {
        val secretKeySpec = SecretKeySpec(key.toByteArray(), "AES")
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)
        return cipher.doFinal(content.toByteArray())
    }

    /**
     * AES 解密
     */
    fun textDecrypt(content: ByteArray, key: String): String {
        val secretKeySpec = SecretKeySpec(key.toByteArray(), "AES")
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec)
        return cipher.doFinal(content).toString()
    }

    /**
     * base64加密，可逆
     * Base64.NO_WRAP 不换行不加空格
     */
    fun toBase64(message: String) = runCatching {
        Base64.encodeToString(message.toByteArray(), Base64.NO_WRAP)
    }.getOrDefault(message)

    /**
     * sha-256加密
     * @param message JSON格式
     */
    fun toSHA256(message: String) = runCatching {
//        val json = JSONObject.parseObject(message)
//        val sortJsonStr = JSONObject.toJSONString(json, SerializerFeature.MapSortField)
//        val messageDigest = MessageDigest.getInstance("SHA-256")
//        messageDigest.update(sortJsonStr.toByteArray(Charsets.UTF_8))
//        byte2Hex(messageDigest.digest())
    }

    /**
     * 同 encodeHex
     */
    private fun byte2Hex(bytes: ByteArray): String {
        val stringBuffer = StringBuffer()
        var strTemp: String? = null
        for (i in bytes.indices) {
            strTemp = Integer.toHexString(bytes[i].toInt() and 0xFF)
            if (strTemp.length == 1) {
                stringBuffer.append("0")
            }
            stringBuffer.append(strTemp)
        }
        return stringBuffer.toString()
    }

    /**
     * 获得手机号，需要申请权限
     */
    @SuppressLint("HardwareIds")
    @Composable
    fun getPhone(context: Activity): String {

        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED){

            var phone = (context.getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager)?.line1Number
            if (phone.isNullOrEmpty()){
                val subscriptionInfoList = (context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as? SubscriptionManager)?.activeSubscriptionInfoList
                if (subscriptionInfoList.isNullOrEmpty()){

                }else {
                    phone = subscriptionInfoList[0].number
                }
            }

        }else {
            PermissionUtil.CheckSinglePermission(
                Manifest.permission.READ_SMS,
                execute = {

                }, denial = {

                })
        }
        return ""
    }

    /**
     * 获得有线mac地址，mac地址为空则取uuid
     */
    fun getMac(): String{
        var macSerial: String? = null
        var macAddress: String? = null
        var input: LineNumberReader? = null
        try {
            val pp = Runtime.getRuntime().exec("cat /sys/class/net/eth0/address")
            val ir = InputStreamReader(pp.inputStream)
            input = LineNumberReader(ir)
            if (input.readLine().also { macAddress = it } != null) {
                macSerial = macAddress!!.trim { it <= ' ' }
            }
        }catch (e: Exception){
            e.printStackTrace()
        }finally {
            runCatching {
                input?.close()
            }
        }
        val macId = macSerial?.replace(":".toRegex(), "")
        return if (TextUtils.isEmpty(macId)) UUID.randomUUID().toString() else macId?: ""
    }

    /**
     * 修改主题饱和度
     */
    fun pageGrey(context: Activity){
        val colorMatrix = ColorMatrix()
        colorMatrix.setSaturation(0.0f)
        val paint = Paint()
        paint.colorFilter = ColorMatrixColorFilter(colorMatrix)
        context.window.decorView.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
    }

}